package com.qianfeng.smartdevices.service.impl;


//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼            BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  


import com.github.pagehelper.PageInfo;
import com.qianfeng.smartdevices.cache.CategoriesCache;
import com.qianfeng.smartdevices.dto.ResultCode;
import com.qianfeng.smartdevices.event.CategoryChangeEvent;
import com.qianfeng.smartdevices.exceptions.AddErrorException;
import com.qianfeng.smartdevices.exceptions.DeleteErrorException;
import com.qianfeng.smartdevices.exceptions.MybaseException;
import com.qianfeng.smartdevices.exceptions.UpdateErrorException;
import com.qianfeng.smartdevices.mapper.CategoryMapper;
import com.qianfeng.smartdevices.pojo.Category;
import com.qianfeng.smartdevices.pojo.CheckStatus;
import com.qianfeng.smartdevices.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by jackiechan on 2020/12/9 22:57
 *
 * @Author jackiechan
 */
@Service
@Transactional
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private ApplicationContext context;
    @Autowired
    private CategoriesCache categoriesCache;

    @Autowired
    private CategoryChangeEvent event;

    @Override
    public void addCategory(Category category) {

        if (category == null || category.isNull(CheckStatus.ADD)) {
            throw new AddErrorException("数据为空", ResultCode.DATA_NOT_ALLOW_NUL);
        }

        try {
            categoryMapper.addCategory(category);
            context.publishEvent(event);//更新缓存
        } catch (Exception e) {
            e.printStackTrace();
            throw new AddErrorException(e.getMessage(), ResultCode.DATA_NOT_ALLOW_NUL);

        }
    }

    @Override
    public void updateCategory(Category category) {
        if (category == null || category.getId() == null || (StringUtils.isEmpty(category.getTxcommand()) && StringUtils.isEmpty(category.getCategoryname()))) {
            throw new UpdateErrorException("分类信息不完整", ResultCode.DATA_NOT_ALLOW_NUL);
        }
        try {
            categoryMapper.updateCategory(category);//更新分类
            context.publishEvent(event);//更新缓存
        } catch (Exception e) {
            e.printStackTrace();
            throw new UpdateErrorException(e.getMessage(), ResultCode.DATA_NOT_ALLOW_NUL);

        }
    }

    @Override
    public Category getCategoryById(Long id) {
        if (id == null) {
            throw new MybaseException("id 不能为空", ResultCode.DATA_NOT_ALLOW_NUL);
        }
        Category category = categoriesCache.get(id);
        if (category != null) {
            return category;
        }
        throw new MybaseException("无此分类", ResultCode.DATA_NOT_ALLOW_NUL);
    }

    @Override
    public PageInfo<Category> getAllCategoriesByPage(int page, int limit, String categoryname, String status) {

        // PageHelper.startPage(page, limit);
        PageInfo<Category> pageInfo = null;
        // List<Categories> categoriesList = categoryMapper.findAllCategories();
        List<Category> categoriesList = categoriesCache.getAllData();//缓存中如果没有数据,我们不查询数据库,因为缓存中没有基本就代表了数据库中也没有
        //根据条件切割上面的集合
        //集合现在有 19 条数据, 我们要第2页,要 10 条
//        if (categoriesList.size() <= page * limit) {
//            //当我们要的数据不是第一页的时候,会出现将第一页的数据也返回,因为会出现超过一页,但是不能满满的刚好到第二或者更多页
//            pageInfo = new PageInfo<>(categoriesList);
//        }else{
//            //裁剪集合
//            List<Categories> subList = categoriesList.subList((page - 1) * limit, page * limit);
//            pageInfo = new PageInfo<>(subList);
//        }
        // int start_index = 0;

        //遍历集合,判断每条数据是不是符合我们的查询条件
        List<Category> realCategoriesList = categoriesList.stream().filter(categories -> {
            boolean isFetchName = true;
            boolean isFetchStatus = true;
            String categoryname1 = categories.getCategoryname(); //获取对象上面的分类名,用于和名字进行判断的
            String status1 = categories.getStatus();//获取对象上面的状态
            if (!StringUtils.isEmpty(categoryname)) {
                //代表传递了分类的名字
                isFetchName = categoryname1.contains(categoryname);//判断分类的名字中是否包含传递的名字
            }
//
            if (!StringUtils.isEmpty(status) && !"-100".equals(status)) {//如果传递了状态并且不是默认的无状态
                //判断对象的状态和查询的状态是否一致
                isFetchStatus = status.equals(status1);
            }


            return isFetchName && isFetchStatus;//stream 的 filter 要求返回一个 boolean,我们返回的就是是否匹配传递的用户名和状态条件

        }).collect(Collectors.toList());


        //=================华丽的分割线,准备切割符合条件的集合===================
//        int last_index = limit;//为了防止第一页没有数据,所以默认就写 limit
//
//        if (page * limit >= realCategoriesList.size()) { //为了防止出现在切割集合的时候出现数组越界
//            last_index = realCategoriesList.size();//如果超出了总长度,则最后的一个切割下标就是总长度
//        }else{
//            last_index=page * limit;//在不超出范围的情况下就是当前页*每页的数量
//        }
//
//        if ((page - 1) * limit >= realCategoriesList.size()) {
//            //起点超出查询范围了,直接返回空数据
//            pageInfo = new PageInfo<>();
//            return pageInfo;
//        }
        //切割集合,上面的代码都是怕越界而做的判断
        List<Category> subList = realCategoriesList.stream().skip((page - 1) * limit).limit(limit).collect(Collectors.toList());
        pageInfo = new PageInfo<>(subList);
        pageInfo.setTotal(realCategoriesList.size());//设置总长度为符合条件的集合的长度
        return pageInfo;
    }


    @Override
    public List<Category> getAllCategories() {
        //理论上缓存中的数据是完整的,所以直接返回
        return categoriesCache.getAllData();
    }

    @Override
    public void deleteCategories(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new DeleteErrorException("没有传递 id", ResultCode.DATA_NOT_ALLOW_NUL);
        }
        try {
            //遍历删除
            categoryMapper.deleteCategories(ids);
            //因为传过来是字符串,先转成数字,再删除数据
//            ids.stream().map(Long::parseLong).forEach(id -> {
//                categoryCache.deleteCache(id, null);//从缓存中删除 //TODO 此处可以使用事件异步发送后执行,这样可以减少因为更新缓存异常带来的其他影响, 更新缓存不应该影响业务本身
//            });
            context.publishEvent(event);//更新缓存
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
}
